#define RS 8
#define E 9
#define D4 10
#define D5 11
#define D6 12
#define D7 13

#define dW 12   // Ширина экрана в символах
#define dH 2

unsigned long scrUpd = 0;
int scrPeriod = 200; //ms
LiquidCrystalRus lcd(RS, E, D4, D5, D6, D7);

byte char3_3[8] = {
  0b00000,
  0b11011,
  0b01001,
  0b11011,
  0b01001,
  0b11011,
  0b00100,
  0b00000
};

byte char5[8] = {
  0b00000,
  0b11011,
  0b10011,
  0b11011,
  0b01011,
  0b11011,
  0b00100,
  0b00000
};

byte char9[8] = {
  0b00000,
  0b11011,
  0b11011,
  0b11011,
  0b01011,
  0b11011,
  0b00100,
  0b00000
};

byte char12[8] = {
  0b00000,
  0b01011,
  0b11001,
  0b01001,
  0b01010,
  0b01011,
  0b00000,
  0b00000
};

byte char15[8] = {
  0b00000,
  0b01011,
  0b11010,
  0b01011,
  0b01001,
  0b01011,
  0b00000,
  0b00000
};

byte char24[8] = {
  0b00000,
  0b11011,
  0b01011,
  0b01011,
  0b10001,
  0b11001,
  0b00000,
  0b00000
};

byte charA[8] = {
  0b00000,
  0b00000,
  0b01100,
  0b10101,
  0b10100,
  0b11100,
  0b10101,
  0b00000
};

byte charV[8] = {
  0b00000,
  0b00000,
  0b10100,
  0b10101,
  0b10100,
  0b10100,
  0b01001,
  0b00000
};

void lcd_init() {
  lcd.begin(dW, dH);
  lcd.createChar(0, char3_3);
  lcd.createChar(1, char5);
  lcd.createChar(2, char9);
  lcd.createChar(3, char12);
  lcd.createChar(4, char15);
  lcd.createChar(5, char24);
  lcd.createChar(6, charA);
  lcd.createChar(7, charV);
}

void lcd_swipeRight(){
  for(int i = 0; i < (dW+2); i++){
    lcd.scrollDisplayLeft(); 
    delay(50);
  } 
}

void lcd_swipeLeft(){
  for(int i = 0; i < (dW+2); i++){
    lcd.scrollDisplayRight();
    delay(50); 
  } 
}

void lcd_splash() {
  lcd.clear();
  lcd.setCursor((dW/2-3),0);
  lcd.print("ЦБП-01");  
  lcd.setCursor((dW/2-5),1);
  lcd.print("by AlexxNB");
  delay(1000);
  lcd_swipeLeft();
}

// Основной экран
void lcd_screen1(){
  if(!nextUpdate()) return;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.write((uint8_t)7);
  lcd.print(meter_V(),3);
  lcd.print("B");
  lcd.setCursor(0,1);
  lcd.write((uint8_t)6);
  lcd.print(meter_A(),3);
  lcd.print("A");
  
  setVIcon();
}

// Напряжение
void lcd_screen2(){
  if(!nextUpdate()) return;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Напряжение");
  lcd.setCursor((dW/2-3),1);
  lcd.print(meter_V());
  lcd.print(" B");
  
  setVIcon();
}

void lcd_screen3(){
  if(!nextUpdate()) return;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Ток");
  lcd.setCursor((dW/2-3),1);
  lcd.print(meter_A());
  lcd.print(" A");
  
  setVIcon();
}

void lcd_screen4(){
  if(!nextUpdate()) return;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Мощность");
  lcd.setCursor((dW/2-4),1);
  lcd.print(meter_A()*meter_V());
  lcd.print(" Вт");
  
  setVIcon();
}

void lcd_screen10(int volts){
  if(!nextUpdate()) return;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Выходное V");

  lcd.setCursor(1,1);
  if(volts > 0) lcd.print("<");
  lcd.setCursor(dW-2,1);
  if(volts < 6) lcd.print(">");

  lcd.setCursor((dW/2-3),1);
  if(volts == v3_3) lcd.print("3.3 B ");
  else if(volts == v5) lcd.print("5.0 B ");
  else if(volts == v9) lcd.print("9.0 B ");
  else if(volts == v12) lcd.print(" 12 B ");
  else if(volts == v15) lcd.print(" 15 B ");
  else if(volts == v24) lcd.print(" 24 B ");
  else if(volts == manual) lcd.print("Ручной");
}

void lcd_screen11(int restore){
  if(!nextUpdate()) return;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Сохр. выход");

  lcd.setCursor(1,1);
  lcd.print("<");
  lcd.setCursor(dW-2,1);
  lcd.print(">");

  lcd.setCursor((dW/2-2),1);
  if(restore == 1) lcd.print(" да ");
  else if(restore == 0) lcd.print("нет ");
}

void lcd_screen100(){
  if(!nextUpdate()) return;
  lcd.clear();
  lcd.setCursor((dW/2-4),0);
  lcd.print("ВНИМАНИЕ!");
  lcd.setCursor((dW/2-5),1);
  lcd.print("Перегрузка");
}


void setVIcon(){
  lcd.setCursor(dW-1,0);
  int mode = regulator_getVoltage();
  if(mode == 0)
    lcd.print("*");
  else
    lcd.write((uint8_t)(mode-1));

  if(regulator_getState())
  {
    lcd.setCursor(dW-1,1);
    lcd.print("^");
  }
}

bool nextUpdate(){
  unsigned long ms = millis();
  if((ms - scrUpd) < scrPeriod) return false;
  scrUpd = ms;
  return true;
}
